home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / topten.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  18.8 KB  |  774 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)topten.c    3.1    92/11/20    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #ifdef VMS
  8.  /* We don't want to rewrite the whole file, because that entails     */
  9.  /* creating a new version which requires that the old one be deletable. */
  10. # define UPDATE_RECORD_IN_PLACE
  11. #endif
  12.  
  13. /*
  14.  * Updating in place can leave junk at the end of the file in some
  15.  * circumstances (if it shrinks and the O.S. doesn't have a straightforward
  16.  * way to truncate it).  The trailing junk is harmless and the code
  17.  * which reads the scores will ignore it.
  18.  */
  19. #ifdef UPDATE_RECORD_IN_PLACE
  20. # ifndef SEEK_SET
  21. #  define SEEK_SET 0
  22. # endif
  23. static long final_fpos;
  24. #endif
  25.  
  26. #ifdef NO_SCAN_BRACK
  27. static void FDECL(nsb_mung_line,(char*));
  28. static void FDECL(nsb_unmung_line,(char*));
  29. #endif
  30.  
  31. #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
  32. #define dealloc_ttentry(ttent) free((genericptr_t) (ttent))
  33. #define    NAMSZ    10
  34. #define    DTHSZ    60
  35. #define    PERSMAX     3        /* entries per name/uid per char. allowed */
  36. #define    POINTSMIN    1    /* must be > 0 */
  37. #define    ENTRYMAX    100    /* must be >= 10 */
  38.  
  39. #if !defined(MICRO) && !defined(MAC)
  40. #define    PERS_IS_UID        /* delete for PERSMAX per name; now per uid */
  41. #endif
  42. struct toptenentry {
  43.     struct toptenentry *tt_next;
  44. #ifdef UPDATE_RECORD_IN_PLACE
  45.     long fpos;
  46. #endif
  47.     long points;
  48.     int deathdnum, deathlev;
  49.     int maxlvl,hp,maxhp;
  50.     int uid;
  51.     char plchar;
  52.     char sex;
  53.     char name[NAMSZ+1];
  54.     char death[DTHSZ+1];
  55.     char date[7];        /* yymmdd */
  56. } *tt_head;
  57.  
  58. static void NDECL(outheader);
  59. static int FDECL(outentry, (int,struct toptenentry *,int));
  60. static void FDECL(readentry, (FILE *,struct toptenentry *));
  61. static void FDECL(writeentry, (FILE *,struct toptenentry *));
  62. static int FDECL(classmon, (CHAR_P,BOOLEAN_P));
  63.  
  64. /* must fit with end.c */
  65. NEARDATA const char *killed_by_prefix[] = {
  66.     "killed by ", "choked on ", "poisoned by ", "", "drowned in ",
  67.     "", "crushed to death by ", "petrified by ", "",
  68.     "", "",
  69.     "", "", "" };
  70.  
  71. static void
  72. readentry(rfile,tt)
  73. FILE *rfile;
  74. struct toptenentry *tt;
  75. {
  76. #ifdef UPDATE_RECORD_IN_PLACE
  77.     /* note: fscanf() below must read the record's terminating newline */
  78.     final_fpos = tt->fpos = ftell(rfile);
  79. #endif
  80. #define TTFIELDS 12
  81. #ifdef NO_SCAN_BRACK
  82.     if(fscanf(rfile,"%6s %d %d %d %d %d %d %ld%*c%c%c %s %s%*c",
  83. #else
  84.     if(fscanf(rfile, "%6s %d %d %d %d %d %d %ld %c%c %[^,],%[^\n]%*c",
  85. #endif
  86.             tt->date, &tt->uid,
  87.             &tt->deathdnum, &tt->deathlev,
  88.             &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->points,
  89.             &tt->plchar, &tt->sex,
  90.             tt->name, tt->death) != TTFIELDS)
  91. #undef TTFIELDS
  92.         tt->points = 0;
  93.     else {
  94. #ifdef NO_SCAN_BRACK
  95.         if(tt->points > 0) {
  96.             nsb_unmung_line(tt->name);
  97.             nsb_unmung_line(tt->death);
  98.         }
  99. #endif
  100.     }
  101. }
  102.  
  103. static void
  104. writeentry(rfile,tt)
  105. FILE *rfile;
  106. struct toptenentry *tt;
  107. {
  108. #ifdef NO_SCAN_BRACK
  109.     nsb_mung_line(tt->name);
  110.     nsb_mung_line(tt->death);
  111.     (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s %s\n",
  112. #else
  113.     (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s,%s\n",
  114. #endif
  115.         tt->date, tt->uid,
  116.         tt->deathdnum, tt->deathlev,
  117.         tt->maxlvl, tt->hp, tt->maxhp, tt->points,
  118.         tt->plchar, tt->sex,
  119.         onlyspace(tt->name) ? "_" : tt->name, tt->death);
  120. #ifdef NO_SCAN_BRACK
  121.     nsb_unmung_line(tt->name);
  122.     nsb_unmung_line(tt->death);
  123. #endif
  124. }
  125.  
  126. void
  127. topten(how)
  128. int how;
  129. {
  130.     int uid = getuid();
  131.     int rank, rank0 = -1, rank1 = 0;
  132.     int occ_cnt = PERSMAX;
  133.     register struct toptenentry *t0, *tprev;
  134.     struct toptenentry *t1;
  135.     FILE *rfile;
  136.     register int flg = 0;
  137. #ifdef LOGFILE
  138.     FILE *lfile;
  139. #endif /* LOGFILE */
  140.  
  141. #if defined(MICRO)
  142. #define HUP
  143. #else
  144. #define    HUP    if(!done_hup)
  145. #endif
  146.  
  147. #ifdef TOS
  148.     restore_colors();    /* make sure the screen is black on white */
  149. #endif
  150.     /* create a new 'topten' entry */
  151.     t0 = newttentry();
  152.     /* deepest_lev_reached() is in terms of depth(), and reporting the
  153.      * deepest level reached in the dungeon death occurred in doesn't
  154.      * seem right, so we have to report the death level in depth() terms
  155.      * as well (which also seems reasonable since that's all the player
  156.      * sees on the screen anyway)
  157.      */
  158.     t0->deathdnum = u.uz.dnum;
  159.     t0->deathlev = depth(&u.uz);
  160.     t0->maxlvl = deepest_lev_reached(TRUE);
  161.     t0->hp = u.uhp;
  162.     t0->maxhp = u.uhpmax;
  163.     t0->points = u.urexp;
  164.     t0->plchar = pl_character[0];
  165.     t0->sex = (flags.female ? 'F' : 'M');
  166.     t0->uid = uid;
  167.     (void) strncpy(t0->name, plname, NAMSZ);
  168.     t0->name[NAMSZ] = '\0';
  169.     t0->death[0] = '\0';
  170.     switch (killer_format) {
  171.         default: impossible("bad killer format?");
  172.         case KILLED_BY_AN:
  173.             Strcat(t0->death, killed_by_prefix[how]);
  174.             (void) strncat(t0->death, an(killer),
  175.                         DTHSZ-strlen(t0->death));
  176.             break;
  177.         case KILLED_BY:
  178.             Strcat(t0->death, killed_by_prefix[how]);
  179.             (void) strncat(t0->death, killer,
  180.                         DTHSZ-strlen(t0->death));
  181.             break;
  182.         case NO_KILLER_PREFIX:
  183.             (void) strncat(t0->death, killer, DTHSZ);
  184.             break;
  185.     }
  186.     Strcpy(t0->date, get_date());
  187.     t0->tt_next = 0;
  188. #ifdef UPDATE_RECORD_IN_PLACE
  189.     t0->fpos = -1L;
  190. #endif
  191.  
  192. #ifdef LOGFILE        /* used for debugging (who dies of what, where) */
  193.     if (lock_file(LOGFILE, 10)) {
  194.         if(!(lfile = fopen_datafile(LOGFILE,"a"))) {
  195.         HUP raw_print("Cannot open log file!");
  196.         } else {
  197.         writeentry(lfile, t0);
  198.         (void) fclose(lfile);
  199.         }
  200.         unlock_file(LOGFILE);
  201.     }
  202. #endif /* LOGFILE */
  203.  
  204. #if defined(WIZARD) || defined(EXPLORE_MODE)
  205.     if (wizard || discover) {
  206.         HUP {
  207.         raw_print("");
  208.         raw_printf(
  209.           "Since you were in %s mode, the score list will not be checked.",
  210.             wizard ? "wizard" : "discover");
  211.         }
  212.         return;
  213.     }
  214. #endif
  215.  
  216.     if (!lock_file(RECORD, 60)) return;
  217.  
  218. #ifdef UPDATE_RECORD_IN_PLACE
  219.     rfile = fopen_datafile(RECORD, "r+");
  220. #else
  221.     rfile = fopen_datafile(RECORD, "r");
  222. #endif
  223.  
  224.     if (!rfile) {
  225.         HUP raw_print("Cannot open record file!");
  226.         unlock_file(RECORD);
  227.         return;
  228.     }
  229.  
  230.     HUP raw_print("");
  231.  
  232.     /* assure minimum number of points */
  233.     if(t0->points < POINTSMIN) t0->points = 0;
  234.  
  235.     t1 = tt_head = newttentry();
  236.     tprev = 0;
  237.     /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
  238.     for(rank = 1; ; ) {
  239.         readentry(rfile, t1);
  240.         if (t1->points < POINTSMIN) t1->points = 0;
  241.         if(rank0 < 0 && t1->points < t0->points) {
  242.         rank0 = rank++;
  243.         if(tprev == 0)
  244.             tt_head = t0;
  245.         else
  246.             tprev->tt_next = t0;
  247.         t0->tt_next = t1;
  248. #ifdef UPDATE_RECORD_IN_PLACE
  249.         t0->fpos = t1->fpos;    /* insert here */
  250. #endif
  251.         occ_cnt--;
  252.         flg++;        /* ask for a rewrite */
  253.         } else tprev = t1;
  254.  
  255.         if(t1->points == 0) break;
  256.         if(
  257. #ifdef PERS_IS_UID
  258.         t1->uid == t0->uid &&
  259. #else
  260.         strncmp(t1->name, t0->name, NAMSZ) == 0 &&
  261. #endif
  262.         t1->plchar == t0->plchar && --occ_cnt <= 0) {
  263.             if(rank0 < 0) {
  264.             rank0 = 0;
  265.             rank1 = rank;
  266.             HUP {
  267.                 raw_printf(
  268.               "You didn't beat your previous score of %ld points.",
  269.                     t1->points);
  270.                 raw_print("");
  271.             }
  272.             }
  273.             if(occ_cnt < 0) {
  274.             flg++;
  275.             continue;
  276.             }
  277.         }
  278.         if(rank <= ENTRYMAX) {
  279.         t1 = t1->tt_next = newttentry();
  280.         rank++;
  281.         }
  282.         if(rank > ENTRYMAX) {
  283.         t1->points = 0;
  284.         break;
  285.         }
  286.     }
  287.     if(flg) {    /* rewrite record file */
  288. #ifdef UPDATE_RECORD_IN_PLACE
  289.         (void) fseek(rfile, (t0->fpos >= 0 ?
  290.                      t0->fpos : final_fpos), SEEK_SET);
  291. #else
  292.         (void) fclose(rfile);
  293.         if(!(rfile = fopen_datafile(RECORD,"w"))){
  294.             HUP raw_print("Cannot write record file");
  295.             unlock_file(RECORD);
  296.             return;
  297.         }
  298. #endif    /* UPDATE_RECORD_IN_PLACE */
  299.         if(!done_stopprint) if(rank0 > 0){
  300.             if(rank0 <= 10)
  301.             raw_print("You made the top ten list!");
  302.             else {
  303.             raw_printf(
  304.               "You reached the %d%s place on the top %d list.",
  305.                 rank0, ordin(rank0), ENTRYMAX);
  306.             }
  307.             raw_print("");
  308.         }
  309.     }
  310.     if(rank0 == 0) rank0 = rank1;
  311.     if(rank0 <= 0) rank0 = rank;
  312.     if(!done_stopprint) outheader();
  313.     t1 = tt_head;
  314.     for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
  315.         if(flg
  316. #ifdef UPDATE_RECORD_IN_PLACE
  317.             && rank >= rank0
  318. #endif
  319.         ) writeentry(rfile, t1);
  320.         if(done_stopprint) continue;
  321.         if(rank > flags.end_top &&
  322.           (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
  323.           && (!flags.end_own ||
  324. #ifdef PERS_IS_UID
  325.                   t1->uid != t0->uid
  326. #else
  327.                   strncmp(t1->name, t0->name, NAMSZ)
  328. #endif
  329.         )) continue;
  330.         if(rank == rank0-flags.end_around &&
  331.            rank0 > flags.end_top+flags.end_around+1 &&
  332.            !flags.end_own)
  333.           raw_print("");
  334.         if(rank != rank0)
  335.         (void) outentry(rank, t1, 0);
  336.         else if(!rank1)
  337.         (void) outentry(rank, t1, 1);
  338.         else {
  339.         int t0lth = outentry(0, t0, -1);
  340.         int t1lth = outentry(rank, t1, t0lth);
  341.         if(t1lth > t0lth) t0lth = t1lth;
  342.         (void) outentry(0, t0, t0lth);
  343.         }
  344.     }
  345.     if(rank0 >= rank) if(!done_stopprint)
  346.         (void) outentry(0, t0, 1);
  347. #ifdef UPDATE_RECORD_IN_PLACE
  348.     if (flg) {
  349. # ifdef TRUNCATE_FILE
  350.         /* if a reasonable way to truncate a file exists, use it */
  351.         truncate_file(rfile);
  352. # else
  353.         /* use sentinel record rather than relying on truncation */
  354.         t0->points = 0L;    /* terminates file when read back in */
  355.         t0->uid = t0->deathdnum = t0->deathlev = 0;
  356.         t0->maxlvl = t0->hp = t0->maxhp = 0;
  357.         t0->plchar = t0->sex = '-';
  358.         Strcpy(t0->name, "@");
  359.         Strcpy(t0->death, "<eod>\n");
  360.         writeentry(rfile, t0);
  361.         (void) fflush(rfile);
  362. # endif    /* TRUNCATE_FILE */
  363.     }
  364. #endif    /* UPDATE_RECORD_IN_PLACE */
  365.     (void) fclose(rfile);
  366.     unlock_file(RECORD);
  367. }
  368.  
  369. static void
  370. outheader() {
  371.     char linebuf[BUFSZ];
  372.     register char *bp;
  373.  
  374.     Strcpy(linebuf, " No  Points     Name");
  375.     bp = eos(linebuf);
  376.     while(bp < linebuf + COLNO - 9) *bp++ = ' ';
  377.     Strcpy(bp, "Hp [max]");
  378.     raw_print(linebuf);
  379. }
  380.  
  381. /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
  382. static int
  383. outentry(rank, t1, so)
  384. register struct toptenentry *t1;
  385. register int rank, so;
  386. {
  387.     register boolean second_line = TRUE;
  388.     char linebuf[BUFSZ], linebuf2[BUFSZ], linebuf3[BUFSZ], pbuf[BUFSZ];
  389.  
  390.     linebuf[0] = linebuf2[0] = linebuf3[0] = 0;
  391.     if(rank) Sprintf(eos(linebuf), "%3d", rank);
  392.     else Strcat(linebuf, "   ");
  393.  
  394.     Sprintf(eos(linebuf), " %10ld  %.10s", t1->points, t1->name);
  395.     Sprintf(eos(linebuf), "-%c ", t1->plchar);
  396.     if(!strncmp("escaped", t1->death, 7)) {
  397.       second_line = FALSE;
  398.       if(!strcmp(" (with the Amulet)", t1->death+7))
  399.         Strcat(linebuf, "escaped the dungeon with the Amulet");
  400.       else
  401.         Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
  402.           t1->maxlvl);
  403.     } else if(!strncmp("ascended", t1->death, 8)) {
  404.        Strcat(linebuf, "ascended to demigod");
  405.        if (t1->sex == 'F') Strcat(linebuf, "dess");
  406.        Strcat(linebuf, "-hood");
  407.        second_line = FALSE;
  408.     } else {
  409.       if(!strncmp(t1->death,"quit",4)) {
  410.         Strcat(linebuf, "quit");
  411.         second_line = FALSE;
  412.       } else if(!strncmp(t1->death,"starv",5)) {
  413.         Strcat(linebuf, "starved to death");
  414.         second_line = FALSE;
  415.       } else if(!strncmp(t1->death,"choked",6)) {
  416.         Sprintf(eos(linebuf), "choked on h%s food",
  417.             (t1->sex == 'F') ? "er" : "is");
  418.       } else if(!strncmp(t1->death,"poisoned",8)) {
  419.         Strcat(linebuf, "was poisoned");
  420.       } else if(!strncmp(t1->death,"crushed",7)) {
  421.         Strcat(linebuf, "was crushed to death");
  422.       } else if(!strncmp(t1->death, "petrified by ",13)) {
  423.         Strcat(linebuf, "turned to stone");
  424.       } else Strcat(linebuf, "died");
  425.  
  426.       if (t1->deathdnum == astral_level.dnum)
  427.         Strcpy(linebuf3, " in the endgame");
  428.       else
  429.         Sprintf(linebuf3, " in %s on level %d",
  430.             dungeons[t1->deathdnum].dname, t1->deathlev);
  431.       if(t1->deathlev != t1->maxlvl)
  432.         Sprintf(eos(linebuf3), " [max %d]", t1->maxlvl);
  433.       /* kludge for "quit while already on Charon's boat" */
  434.       if(!strncmp(t1->death, "quit ", 5))
  435.         Strcat(linebuf3, t1->death + 4);
  436.     }
  437.     Strcat(linebuf3, ".");
  438.  
  439.     if(t1->maxhp) {
  440.       register char *bp;
  441.       char hpbuf[10];
  442.       int hppos;
  443.       int lngr = strlen(linebuf) + strlen(linebuf3);
  444.       if (t1->hp <= 0) hpbuf[0] = '-', hpbuf[1] = '\0';
  445.       else Sprintf(hpbuf, "%d", t1->hp);
  446.       hppos = COLNO - 7 - (int)strlen(hpbuf);
  447.       if (lngr >= hppos) {
  448.           if(so > 0) {
  449.           bp = eos(linebuf);
  450.           while(bp < linebuf + (COLNO-1)) *bp++ = ' ';
  451.           *bp = 0;
  452.           raw_print_bold(linebuf);
  453.           } else if(so == 0)
  454.           raw_print(linebuf);
  455.           Strcpy(linebuf, "               ");
  456.       }
  457.       Strcat(linebuf, linebuf3);
  458.       bp = eos(linebuf);
  459.  
  460.       if(bp <= linebuf + hppos) {
  461.         /* pad any necessary blanks to the hit point entry */
  462.         while(bp < linebuf + hppos) *bp++ = ' ';
  463.         Strcpy(bp, hpbuf);
  464.         if(t1->maxhp < 10)
  465.          Sprintf(eos(bp), "   [%d]", t1->maxhp);
  466.         else if(t1->maxhp < 100)
  467.          Sprintf(eos(bp), "  [%d]", t1->maxhp);
  468.         else Sprintf(eos(bp), " [%d]", t1->maxhp);
  469.       }
  470.     }
  471.  
  472. /*    Line 2 now contains the killer name */
  473.  
  474.     /* Quit, starved, ascended, and escaped contain no second line */
  475.     if (second_line) {
  476.         Strcpy(linebuf2, t1->death);
  477.         *linebuf2 = highc(*linebuf2);
  478.         Strcat(linebuf2, ".");
  479.     }
  480.  
  481.     if(so == 0) {
  482.         raw_print(linebuf);
  483.         if (second_line)
  484.         raw_printf("                %s", linebuf2);
  485.     } else if(so > 0) {
  486.       register char *bp = eos(linebuf);
  487.       if(so >= COLNO) so = COLNO-1;
  488.       while(bp < linebuf + so) *bp++ = ' ';
  489.       *bp = 0;
  490.       raw_print_bold(linebuf);
  491.       if(second_line) {
  492.           Sprintf(pbuf, "                %s", linebuf2);
  493.           raw_print_bold(pbuf);
  494.       }
  495.     }
  496.     return((int)strlen(linebuf)+(int)strlen(linebuf2));
  497. }
  498.  
  499. /*
  500.  * Called with args from main if argc >= 0. In this case, list scores as
  501.  * requested. Otherwise, find scores for the current player (and list them
  502.  * if argc == -1).
  503.  */
  504. void
  505. prscore(argc,argv)
  506. int argc;
  507. char **argv;
  508. {
  509.     const char **players;
  510.     int playerct;
  511.     int rank;
  512.     register struct toptenentry *t1, *t2;
  513.     FILE *rfile;
  514.     register int flg = 0, i;
  515.     char pbuf[BUFSZ];
  516. #ifdef nonsense
  517.     long total_score = 0L;
  518.     char totchars[10];
  519.     int totcharct = 0;
  520. #endif
  521.     int outflg = (argc >= -1);
  522. #ifdef PERS_IS_UID
  523.     int uid = -1;
  524. #else
  525.     const char *player0;
  526. #endif
  527.     rfile = fopen_datafile(RECORD, "r");
  528.     if (!rfile) {
  529.         raw_print("Cannot open record file!");
  530.         return;
  531.     }
  532.  
  533. #ifdef    AMIGA
  534.     {
  535.         extern winid amii_rawprwin;
  536.         init_nhwindows();
  537.         amii_rawprwin = create_nhwindow( NHW_TEXT );
  538.     }
  539. #endif
  540.  
  541.     /* If the score list isn't after a game, we never went through */
  542.     /* init_dungeons() */
  543.     if (wiz1_level.dlevel == 0) init_dungeons();
  544.  
  545.     if(argc > 1 && !strncmp(argv[1], "-s", 2)){
  546.         if(!argv[1][2]){
  547.             argc--;
  548.             argv++;
  549.         } else if(!argv[1][3] && index(pl_classes, argv[1][2])) {
  550.             argv[1]++;
  551.             argv[1][0] = '-';
  552.         } else    argv[1] += 2;
  553.     }
  554.     if(argc <= 1){
  555. #ifdef PERS_IS_UID
  556.         uid = getuid();
  557.         playerct = 0;
  558. #  if defined(LINT) || defined(GCC_WARN)
  559.         players = 0;
  560. #  endif
  561. #else
  562.         player0 = plname;
  563.         if(!*player0)
  564. #ifdef AMIGA
  565.             player0 = "all";    /* single user system */
  566. #else
  567.             player0 = "hackplayer";
  568. #endif
  569.         playerct = 1;
  570.         players = &player0;
  571. #endif
  572.     } else {
  573.         playerct = --argc;
  574.         players = (const char **)++argv;
  575.     }
  576.     if(outflg) raw_print("");
  577.  
  578.     t1 = tt_head = newttentry();
  579.     for(rank = 1; ; rank++) {
  580.         readentry(rfile, t1);
  581.         if(t1->points == 0) break;
  582. #ifdef PERS_IS_UID
  583.         if(!playerct && t1->uid == uid)
  584.         flg++;
  585.         else
  586. #endif
  587.         for(i = 0; i < playerct; i++){
  588.         if(strcmp(players[i], "all") == 0 ||
  589.            strncmp(t1->name, players[i], NAMSZ) == 0 ||
  590.           (players[i][0] == '-' &&
  591.            players[i][1] == t1->plchar &&
  592.            players[i][2] == 0) ||
  593.           (digit(players[i][0]) && rank <= atoi(players[i])))
  594.             flg++;
  595.         }
  596.         t1 = t1->tt_next = newttentry();
  597.     }
  598.     (void) fclose(rfile);
  599.     if(!flg) {
  600.         if(outflg) {
  601.         Strcpy(pbuf, "Cannot find any entries for ");
  602.         if(playerct < 1) Strcat(pbuf, "you.");
  603.         else {
  604.           if(playerct > 1) Strcat(pbuf, "any of ");
  605.           for(i=0; i<playerct; i++) {
  606.               Strcat(pbuf, players[i]);
  607.               if(i<playerct-1) Strcat(pbuf, ":");
  608.           }
  609.           raw_print(pbuf);
  610.           raw_printf("Call is: %s -s [-role] [maxrank] [playernames]",
  611.                  hname);
  612.         }
  613.         }
  614. #ifdef    AMIGA
  615.         display_nhwindow( amii_rawprwin, 1 );
  616.         destroy_nhwindow( amii_rawprwin );
  617.         amii_rawprwin = WIN_ERR;
  618. #endif
  619.         return;
  620.     }
  621.  
  622.     if(outflg) outheader();
  623.     t1 = tt_head;
  624.     for(rank = 1; t1->points != 0; rank++, t1 = t2) {
  625.         t2 = t1->tt_next;
  626. #ifdef PERS_IS_UID
  627.         if(!playerct && t1->uid == uid)
  628.             goto outwithit;
  629.         else
  630. #endif
  631.         for(i = 0; i < playerct; i++){
  632.             if(strcmp(players[i], "all") == 0 ||
  633.                strncmp(t1->name, players[i], NAMSZ) == 0 ||
  634.               (players[i][0] == '-' &&
  635.                players[i][1] == t1->plchar &&
  636.                players[i][2] == 0) ||
  637.               (digit(players[i][0]) && rank <= atoi(players[i]))){
  638. #ifdef PERS_IS_UID
  639.             outwithit:
  640. #endif
  641.                 if(outflg)
  642.                     (void) outentry(rank, t1, 0);
  643. #ifdef nonsense
  644.                 total_score += t1->points;
  645.                 if(totcharct < sizeof(totchars)-1)
  646.                     totchars[totcharct++] = t1->plchar;
  647. #endif
  648.                 break;
  649.             }
  650.         }
  651.         dealloc_ttentry(t1);
  652.     }
  653. #ifdef nonsense
  654.     totchars[totcharct] = 0;
  655.  
  656.     /* We would like to determine whether you're experienced.  However,
  657.        the information collected here only tells about the scores/roles
  658.        that got into the topten (top 100?).  We should maintain a
  659.        .hacklog or something in his home directory. */
  660.     flags.beginner = (total_score < 6000);
  661.     for(i=0; i<6; i++)
  662.         if(!index(totchars, pl_classes[i])) {
  663.         flags.beginner = 1;
  664.         if(!pl_character[0]) pl_character[0] = pl_classes[i];
  665.         break;
  666.     }
  667. #endif /* nonsense /**/
  668. #ifdef    AMIGA
  669.     display_nhwindow( amii_rawprwin, 1 );
  670.     destroy_nhwindow( amii_rawprwin );
  671.     amii_rawprwin = WIN_ERR;
  672. #endif
  673. }
  674.  
  675. static int
  676. classmon(plch, fem)
  677. char plch;
  678. boolean fem;
  679. {
  680.     switch (plch) {
  681.         case 'A': return PM_ARCHEOLOGIST;
  682.         case 'B': return PM_BARBARIAN;
  683.         case 'C': return (fem ? PM_CAVEWOMAN : PM_CAVEMAN);
  684.         case 'E': return PM_ELF;
  685.         case 'H': return PM_HEALER;
  686.         case 'F':    /* accept old Fighter class */
  687.         case 'K': return PM_KNIGHT;
  688.         case 'P': return (fem ? PM_PRIESTESS : PM_PRIEST);
  689.         case 'R': return PM_ROGUE;
  690.         case 'N':    /* accept old Ninja class */
  691.         case 'S': return PM_SAMURAI;
  692. #ifdef TOURIST
  693.         case 'T': return PM_TOURIST;
  694. #else
  695.         case 'T': return PM_HUMAN;
  696. #endif
  697.         case 'V': return PM_VALKYRIE;
  698.         case 'W': return PM_WIZARD;
  699.         default: impossible("What weird class is this? (%c)", plch);
  700.             return PM_HUMAN_ZOMBIE;
  701.     }
  702. }
  703.  
  704. /*
  705.  * Get a random player name and class from the high score list,
  706.  * and attach them to an object (for statues or morgue corpses).
  707.  */
  708. struct obj *
  709. tt_oname(otmp)
  710. struct obj *otmp;
  711. {
  712.     int rank;
  713.     register int i;
  714.     register struct toptenentry *tt;
  715.     FILE *rfile;
  716.  
  717.     if (!otmp) return((struct obj *) 0);
  718.  
  719.     rfile = fopen_datafile(RECORD, "r");
  720.     if (!rfile) {
  721.         panic("Cannot open record file!");
  722.     }
  723.  
  724.     tt = newttentry();
  725.     rank = rnd(10);
  726. pickentry:
  727.     for(i = rank; i; i--) {
  728.         readentry(rfile, tt);
  729.         if(tt->points == 0) break;
  730.     }
  731.  
  732.     if(tt->points == 0) {
  733.         if(rank > 1) {
  734.             rank = 1;
  735.             rewind(rfile);
  736.             goto pickentry;
  737.         }
  738.         dealloc_ttentry(tt);
  739.         otmp = (struct obj *) 0;
  740.     } else {
  741.         otmp->corpsenm = classmon(tt->plchar, (tt->sex == 'F'));
  742.         otmp->owt = weight(otmp);
  743.         /* Note: oname() is safe since otmp is first in chains */
  744.         otmp = oname(otmp, tt->name, 0);
  745.         fobj = otmp;
  746.         level.objects[otmp->ox][otmp->oy] = otmp;
  747.         dealloc_ttentry(tt);
  748.     }
  749.  
  750.     (void) fclose(rfile);
  751.     return otmp;
  752. }
  753.  
  754. #ifdef NO_SCAN_BRACK
  755. /* Lattice scanf isn't up to reading the scorefile.  What */
  756. /* follows deals with that; I admit it's ugly. (KL) */
  757. /* Now generally available (KL) */
  758. static void
  759. nsb_mung_line(p)
  760.     char *p;
  761.     {
  762.     while(p=index(p,' '))*p='|';
  763. }
  764.  
  765. static void
  766. nsb_unmung_line(p)
  767.     char *p;
  768.     {
  769.     while(p=index(p,'|'))*p=' ';
  770. }
  771. #endif
  772.  
  773. /*topten.c*/
  774.